package com.lzx.iteam.contactssearch.conversion;

import android.content.Context;
import android.util.Log;
import com.lzx.iteam.util.Constants;
import com.lzx.iteam.util.StringUtil;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EncodingUtils;
import org.json.JSONObject;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PinyinSearch {

    public class ContactInfoNode {
        int nameLength;
        
        String pinyinData;
        
        public String fuzzyString;
        
        public int contactedNumber;
        
        ConcurrentHashMap<String, ArrayList<String>> myRank;
        
        public boolean havePhoneNumber;
    }

    
    
    //only clear contactId dict
    public void clearMemoryData() {
        if (myDialerDict != null) {
            myDialerDict.clear();
        }
        /*if (myContactInfoDict != null) {
            myContactInfoDict.clear();
        }*/
    }
   
    //for business card store
    public ConcurrentHashMap<String, SimpleContact> mBusinessCardGlobal = null;//new ConcurrentHashMap<String, SimpleContact>();
    public ConcurrentHashMap<String, JSONObject> mReciveCard = null;
    private ArrayList<String> mBusinessCardId = new ArrayList<String>();
    public synchronized ArrayList<String> getBusinessCardId() {
        return mBusinessCardId;
    }

    ConcurrentHashMap<Long, ContactInfoNode> myContactInfoDict = new ConcurrentHashMap<Long, ContactInfoNode>();  
    ConcurrentHashMap<String, ConcurrentHashMap<Long, ContactInfoNode>> myGroupContactInfoDict = new ConcurrentHashMap<String, ConcurrentHashMap<Long, ContactInfoNode>>();
    
    HashMap<String, BitSet> myDialerDict = new HashMap<String, BitSet>();
    HashMap<String,HashMap<String, BitSet>> myGroupDialerDict = new HashMap<String,HashMap<String, BitSet>>();
    
    
    
    public ConcurrentHashMap<Long, ContactInfoNode> getContactInfo() {
        return myContactInfoDict;
    }
    
    public void removeContactInfo(long contactId) {
        if (myContactInfoDict.get(contactId) != null) {
            myContactInfoDict.remove(contactId);
        }
    }
    Dictionary<String, ArrayList<ArrayList<String>>> myPinyinRegCacheDict;// =

    HashSet<String> myRegPinyinArray = new HashSet<String>();
    
    public HashMap<Long, HighLightFormat> mContactIdPosition = new HashMap<Long, HighLightFormat>();
    
    public static boolean mHaveNewInput = false;
    
    public static synchronized void setHaveNewInput(boolean value) {
        mHaveNewInput = value;
    }
    
    public static boolean mPersistInterrupted = false;
    
    public static synchronized void setPersistInterrupted(boolean value) {
        mPersistInterrupted = value;
    }
    
    ArrayList<String> myPinyinRegCacheList;

    
    public static class ContactInPersist implements Serializable{
        
        public ArrayList<String> phoneNumber = null;
        
        public ArrayList<String> phoneNumberArea = null;
        
        public String fullName;

//        public HashMap<Long, String> groupInfo = null;
        public HashSet<Long> groupIdSet = null;
        
        public long photoId;
        
        public long rawId = -1;
        
        public String organization;
        
        public String email;
        
        public String fuzzyString;//used for fuzzy search
        
        public int contactedNumber;
        
        public String creationTime;
        
        public long timesContacted;
        
        public long version;
    }

    private static PinyinSearch mInstance;
    
    private Context mContext;
    
    public StringBuilder mHanziPinyin;
    
    public StringBuilder mFirstLetterStr;
    
    public static PinyinSearch getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new PinyinSearch(context);
        }
        return mInstance;
    }

//    private ObjectPoolFactory<HashMap<String, ArrayList<String>>> mRankDictPool;
    /*public ObjectPoolFactory<PhoneNumber> mPhoneNumberPool;
    public ObjectPoolFactory<Organization> mOrganizationPool;
    public ObjectPoolFactory<ExternalDataItem> mExternalDataItemPool;*/
    
    protected PinyinSearch(Context context) {
        mContext = context;
        initMyRegPinyinArray();
    }

    /*
     *  初始化拼音规则数据
     */
    void initMyRegPinyinArray() {
        HashSet<String> set = myRegPinyinArray; 
        byte[] p = new byte[6];
        for (int index = 0; index < 217; index++) {
            int position = index * 6;
            for (int i = 0; i < 6; i++) {
                p[i] = (byte) HanziUtil.Data_Reg_Pinyin.charAt(position + i);
            }
            try {
                String pyr = new String(p, HTTP.US_ASCII).trim();
                set.add(pyr);
                for (int i = 1; i < pyr.length(); i++) {
                    set.add(pyr.substring(0, i));
                }
            } catch (UnsupportedEncodingException e) {
                Log.e(TAG, "initMyRegPinyinArray --> " + e.toString());
            }
        }
    }

    // 将数字字符串首字母变形 -32
    String getFirstCharTransform(String str) {
        if (StringUtil.isEmpty(str)) {
            return str;
        }

        // char firstChar = [str characterAtIndex:0];
        char firstChar = str.charAt(0);
        String leftString = str.substring(1);
        StringBuffer sb = new StringBuffer();

        if ((firstChar >= '2') && (firstChar <= '9')) {
            char c = (char) ((int) firstChar - 32);
            sb.append(c);
            sb.append(leftString);
            return sb.toString();
        } else {
            return str;
        }
    }

    /*
     *  根据字母，得到对应的T9数字
     *  注意姓名中每个字拼音的第一个字母为大写：如小梅：XiaoMei
     *  为了区分汉字的边界，如果字母为大写，则则将该字符减去32，得到一个控制字符，比如：
     *  X对应的数字为9，ASCII值为0x39，减去32为0x19，
     *
     */
    String getT9StrFromLetters(String strLetters) {
        StringBuilder retStr = new StringBuilder();

        int strLettersLength = strLetters.length();
//        char[] Data_Letters_To_T9 = HanziUtil.Data_Letters_To_T9.toCharArray();
        for (int i = 0; i < strLettersLength; i++) {
            char c = strLetters.charAt(i);
            if ((c >= 'a') && (c <= 'z')) {
                c = HanziUtil.Data_Letters_To_T9[c - 'a'];
            } else if ((c >= 'A') && (c <= 'Z')) {
                char temp = HanziUtil.Data_Letters_To_T9[c - 'A'];
                c = (char) ((int) temp - 32);
            } else if ((c >= '2') && (c <= '9')) {
                c -= 32;
            }

            retStr.append(c);
        }

        return retStr.toString();
    }

    // 将字符串首字母大写
    String getFirstCharUppercaseString(String str) {
        if (StringUtil.isEmpty(str)) {
            return str;
        }

        // char firstChar = [str characterAtIndex:0];
        char firstChar = str.charAt(0);
        String leftString = str.substring(1);

        if (((firstChar >= 'a') && (firstChar <= 'z'))
                || ((firstChar >= '2') && (firstChar <= '9'))) {
            return (firstChar - 32) + leftString;
        } else {
            return str;
        }

    }

    class PinyinParm {
        String pinyinSeg;

        ArrayList<String> pinyinNodeList;
    }

   
    ArrayList<ArrayList<String>> getPinyinListByRegReal(String pinyin) {
        if (StringUtil.isEmpty(pinyin)) {
            return null;
        }

        // 获取符合拼音规则的列表(包含完整拼音和部分拼音)
        ArrayList<PinyinParm> pySegStatck = new ArrayList<PinyinParm>();
        ArrayList<ArrayList<String>> retPyList = new ArrayList<ArrayList<String>>();
     
        PinyinParm defaultPym = new PinyinParm();
        defaultPym.pinyinSeg = pinyin;
        defaultPym.pinyinNodeList = new ArrayList<String>();
        pySegStatck.add(defaultPym);
        
        while (pySegStatck.size() > 0) {
            //
            // if (bNewInput) break; get last object
            if (mHaveNewInput) {
                break;
            }
            int size = pySegStatck.size();
            PinyinParm pym = pySegStatck.get(size - 1);
            pySegStatck.remove(size - 1);

            String ps = pym.pinyinSeg;
            if (myRegPinyinArray.contains(ps) || ps.length() == 1) {
                String transform = getFirstCharTransform(ps);
                ArrayList<String> ml = new ArrayList<String>();
                ml.addAll(pym.pinyinNodeList);
                ml.add(transform);
                retPyList.add(ml);
            }

            // 对首字母的各种组合进行处理
            // const unsigned int psLength = [ps length];
            int psLength = ps.length();
            if (psLength > 1) {
                for (int i = 1; i < psLength; i++) {
                    //
                    // if (bNewInput) break;
                    if (mHaveNewInput) {
                        break;
                    }
                    boolean isNotRegPinyin = false;
                    // NSString *prefixPy = [ps substringToIndex:i];
                    String prefixPy = ps.substring(0, i);
                    if (!myRegPinyinArray.contains(prefixPy)) {
                        char curChar = ps.charAt(i - 1);
                        if ((curChar >= '2') && (curChar <= '9'))
                            break;
                        // 如果prefixPy中包含一些特殊字母，不在T9键盘中
                        // prefixPy = [NSString stringWithFormat:@"%c",
                        // curChar];
                        prefixPy = Character.toString(curChar);
                        if (i > 1)
                            isNotRegPinyin = true;
                    }

                    ArrayList<String> newArray = new ArrayList<String>();
                    newArray.addAll(pym.pinyinNodeList);
                    if (isNotRegPinyin) {
                        newArray.add(getFirstCharTransform(ps.substring(0, i - 1)));
                    }
                    newArray.add(getFirstCharTransform(prefixPy));
                    // pym.pinyinNodeList.add(getFirstCharTransform(prefixPy));
                    // [newArray addObject:[self
                    // getFirstCharTransform:prefixPy]];

                    PinyinParm newPm = new PinyinParm();
                    newPm.pinyinSeg = ps.substring(i);// [ps
                                                      // substringFromIndex:i];
                    newPm.pinyinNodeList = newArray;
                    // [pySegStatck addObject:newPm];
                    pySegStatck.add(newPm);
                }
            }
        }
        /*
         * ArrayList<String> lastObject = new ArrayList<String>(); if
         * (retPyList.size() > 0) { // ArrayList<String> lastObject =
         * (ArrayList<String>) retPyList.get(retPyList.size() - 1);
         * lastObject.addAll(retPyList.get(retPyList.size()-1)); }
         */
        int size = retPyList.size();
        if ((size == 0) || retPyList.get(size - 1).size() < pinyin.length()) {
            String upperPinyin = pinyin.toUpperCase();
            ArrayList<String> egSpList = new ArrayList<String>();
            for (int i = 0; i < upperPinyin.length(); i++) {
                //
                // if (bNewInput) break;
                if (mHaveNewInput) {
                    break;
                }
                String subString = Character.toString(upperPinyin.charAt(i));
                egSpList.add(subString);
                // egSpList.add(upperPinyin.substring(i, i + 1));
            }

            // [retPyList addObject:egSpList];
            retPyList.add(egSpList);
        }

        //
        // if (bNewInput) return nil;

        return retPyList;
    }

    // getPinyinListByRegReal 的代理函数，增加了Cache机制
    ArrayList<ArrayList<String>> getPinyinListByReg(String pinyin) {
        
        // NSArray *retList;
        ArrayList<ArrayList<String>> retList = null;
        /*retList = getPinyinListByRegReal(pinyin);
        if (retList == null || retList.size() == 0) {
            return null;
        }
        
        return retList;*/

        if (myPinyinRegCacheDict == null) {
            myPinyinRegCacheDict = new Hashtable<String, ArrayList<ArrayList<String>>>();
        }
        if (myPinyinRegCacheList == null) {
            myPinyinRegCacheList = new ArrayList<String>();
        }

        retList = myPinyinRegCacheDict.get(pinyin);
        if (retList != null) {
            myPinyinRegCacheList.remove(pinyin);
        } else {
            retList = getPinyinListByRegReal(pinyin);
            if (retList == null || retList.size() == 0) {
                return null;
            }
            
            /*for (ArrayList<String> pinyinArray: retList) {
                for (String str: pinyinArray) {
                    LogSystem.v(TAG, "retList" + str);
                }
            }*/
            myPinyinRegCacheDict.put(pinyin, retList);
        }

        myPinyinRegCacheList.add(0, pinyin);

        // MAX_CACHE_PL_SIZE
        if (myPinyinRegCacheList.size() > 100) {
            String pyKey = myPinyinRegCacheList.get(myPinyinRegCacheList.size() - 1);
            myPinyinRegCacheList.remove(myPinyinRegCacheList.size() - 1);
            myPinyinRegCacheDict.remove(pyKey);
        }

        return retList;
    }

    // 获取拼音首字母的组合列表
    HashSet<String> getPyFcSegs(String pyFc) {
        HashSet<String> result = new HashSet<String>(); 
        if (StringUtil.isEmpty(pyFc)) {
            return null;
        }

        // const int pyFcLength = [pyFc length];
        int pyFcLength = pyFc.length();

        if (pyFcLength <= 1) {
            result.add(pyFc);
            return result;
        }

        if (pyFcLength == 2) {
            result.add(pyFc);
            result.add(pyFc.substring(0, 1));
            result.add(pyFc.substring(1));

            return result;
        }

        if (pyFcLength == 3) {
            result.add(pyFc);
            result.add(pyFc.substring(0, 2));
            result.add(pyFc.substring(1));
            result.add(pyFc.substring(0, 1));
            result.add(pyFc.substring(1, 2));
            result.add(pyFc.substring(2));

            return result;
        }

        for (int i = pyFcLength; i > 0; i--) {
            for (int j = 0; j <= pyFcLength - i; j++) {
                result.add(pyFc.substring(j, j + i));
            }
        }

        // return [retList allObjects];
        return result;
    }
    
    /*
     *  获取单个字符(汉字/字母/其他字符)的拼音
     *  UNICODE 中, UNICODE 汉字从 \u3400 到 \u9FFF 中间, \uF900 到 \uFAFF
     *  也有一些, 但是 GB2312 和 Big5 的汉字和字符都是在 \u4E00 到 \u9FFF
     *  中间.
     */
    synchronized void getPinyinReal(char ch, ArrayList<String> retArray) {

        if (retArray == null) return;
        retArray.clear();
        boolean needSetNull = false; 
        if (mHanziPinyin == null) {
            mHanziPinyin = StringUtil.getHanziPinyin(mContext, null);
            needSetNull = true;
        }
        int chCode = (int) ch;
        byte[] p = new byte[6];
        if ((chCode >= 19968) && (chCode < 40870)) {
            for (int count = 0; count < 3; count++) {
                int startPostion = (chCode - 19968) * 18 + count * 6;
                for (int i = 0; i < 6; i++) {
                    p[i] = (byte) mHanziPinyin.charAt(startPostion + i);
                }

                String pinyin = EncodingUtils.getAsciiString(p);

                if (pinyin.equals("      "))
                    break;
                //mContactName = contactName.replaceAll(StringUtil.SAPCE_REGEX, "");
                retArray.add(pinyin.replaceAll(StringUtil.SAPCE_REGEX, ""));
            }
        } else {

            String letter = Character.toString(ch);
            if (letter.length() == 0) {
                retArray.add("_");
            } else {
                if ((ch >= '2') && (ch <= '9')) {
                    retArray.add(Character.toString((char) (ch - 32)));
                } else {
                    retArray.add(letter.toUpperCase());
                }
            }
            // 不可用的字符，返回@ // 返回_ 方便正则表达式匹配
            /*
             * if ([letter length] == 0) { [retArray addObject:@"_"]; } else
             * [retArray addObject:((ch>='2')&&(ch<='9'))? [NSString
             * stringWithFormat:@"%c", ch-32]: [letter uppercaseString]];//0-9 :
             * -32
             */
        }
        
        if (needSetNull) {
            mHanziPinyin = null;
        }
    }

 /*   // getPinyinReal 的代理函数，增加了Cache机制
    ArrayList<String> getPinyin(char ch) {
        // NSArray *retList;
        ArrayList<String> retList = null;

        // Integer key = Character.getNumericValue(ch);
        // Integer key = Integer.parseInt(Character.toString(ch));
//        String key = Character.toString(ch);
//        retList = myPinyinChCachePyDict.get(key);
//        if (retList == null) {
            retList = getPinyinReal(ch);
            // retList = [self getPinyinReal:ch];
//            myPinyinChCachePyDict.put(key, retList);
            // [myPinyinChCachePyDict setObject:retList forKey:key];
//        }

        return retList;
    }*/

    HashSet<String> getKeyFromPinyinList(ArrayList<String> pyList) {
        HashSet<String> retList = new HashSet<String>();
        for (String py : pyList) {
            StringBuffer key = new StringBuffer();
            for (int i = 0; i < py.length(); i++) {
                char c = py.charAt(i);
                if ((c < '2') || ((c > '9') && (c < 'a')) || (c > 'z')) {
                    key.append(c);
                }
            }

            retList.add(key.toString());

        }

        return retList;

    }

    // 从 联系人拼音检索字典(myDialerDict) 中 删除制定联系人对应的所有检索信息
    public void delPinyinDict(String contactName, long contactIndex) {
        ArrayList<String> cachePyList = new ArrayList<String>();
        ArrayList<String> nlPy = new ArrayList<String>();
        
        if (StringUtil.isEmpty(contactName)) {
            return;
        }
        int iLength = contactName.length();
        if (iLength > 20)
            iLength = 20; // 限定最长分析20字符

        ArrayList<String> retArray = new ArrayList<String>();
        for (int i = 0; i < iLength; i++) {
            int cacheListCount = cachePyList.size();// [cachePyList count];
            getPinyinReal(contactName.charAt(i), retArray);
            for (String py : retArray) {
                if (cacheListCount > 0) {
                    for (int cacheIdx = 0; cacheIdx < cacheListCount; cacheIdx++) {
                        String temp = cachePyList.get(cacheIdx) + py;
                        nlPy.add(temp);
                    }
                } else {
                    nlPy.add(py);
                }
            }
            cachePyList.clear();
            cachePyList.addAll(nlPy);
            nlPy.clear();
        }

        ArrayList<String> cacheT9List = new ArrayList<String>();
        for (String cachePy : cachePyList) {
            cacheT9List.add(getT9StrFromLetters(cachePy));
        }

        cachePyList.addAll(cacheT9List);

        HashSet<String> temp = getKeyFromPinyinList(cacheT9List);
        String[] cacheKeyList = new String[temp.size()];
        temp.toArray(cacheKeyList);
        cacheT9List.clear();

        for (String pyKey : cacheKeyList) {
            HashSet<String> tempkeySegs = getPyFcSegs(pyKey);
            String[] keySegs = new String[tempkeySegs.size()];
            tempkeySegs.toArray(keySegs);

            for (String ks : keySegs) {
                BitSet item = myDialerDict.get(ks);
                if (item == null)
                    break;

                if (item.get((int) contactIndex)) {
                    item.clear((int) contactIndex);
                    myContactInfoDict.remove(contactIndex);
                }
            }
        }
        
        //delete other info
        /*if (mContactInMemory.get(contactIndex) != null) {
            mContactInMemory.remove(contactIndex);
        }*/
    }
    
    /*void addContactInfo(long contactId, ContactsInMemory contact) {
        if (mContactInMemory.get(contactId) != null) {
            mContactInMemory.remove(contactId);
        }
        mContactInMemory.put(contactId, contact);
    }*/

    
    public void clearGroupPinyinDict(String groupId)
    {
        ConcurrentHashMap<Long, ContactInfoNode> myContactInfoDict = myGroupContactInfoDict.get(groupId);
        if( myContactInfoDict != null )
        {
        	myContactInfoDict.clear();
        }
    }
    
    
    public void addGroupPinyinDict(String groupId,String contactName, long contactId,boolean havePhoneNumber) 
    {
        if (StringUtil.isEmpty(contactName)) {
            return;
        }
        
        contactName = contactName.replaceAll(StringUtil.SAPCE_REGEX, "");
        ArrayList<String> cachePyList = new ArrayList<String>();
        ArrayList<String> nlPy = new ArrayList<String>();
        
        int iLength = contactName.length();
        if (iLength > 20)
            iLength = 20; // 限定最长分析20字符

        /*
         * cachePyList中存放的是拼音: 如小梅，存放在cachePyList中的为：XiaoMei
         */
        ArrayList<String> retArray = new ArrayList<String>();
        for (int i = 0; i < iLength; i++) {
            // int cacheListCount = [cachePyList count];
            int cacheListCount = cachePyList.size();
            getPinyinReal(contactName.charAt(i), retArray);
            for (String py : retArray) {
                if (cacheListCount > 0) {
                    for (int cacheIdx = 0; cacheIdx < cacheListCount; cacheIdx++) {
                        String temp = cachePyList.get(cacheIdx) + py;
                        nlPy.add(temp);
                    }
                } else {
                    nlPy.add(py);
                }
            }
            cachePyList.clear();
            cachePyList.addAll(nlPy);
            nlPy.clear();
        }
        retArray.clear();
        retArray.add("\u0002");//作为拼音和T9之间的分隔符
        for (String cachePy : cachePyList) {
            retArray.add(getT9StrFromLetters(cachePy));
        }
        //如小梅：cacheT9List中存放的是：[, 42634]： 为分隔符，42634为XiaoMei对应的T9，为9，为6
        cachePyList.addAll(retArray);

        // T9List中存放的是首字母对应的数字，首字母为大写 cacheKeyList存放了所有的首字母，因为一个汉字对应多个拼音:
        // 比如长：Zhang Chang, 如果姓名是长鹏飞,则对应的首字母为ZPF，CPF
        //getKeyFromPinyinList是从cacheT9List中取出key值，如XiaoMei的key值为, , 为分隔符
        HashSet<String> KeySet = getKeyFromPinyinList(retArray);
        /*String[] cacheKeyList = new String[temp.size()];
        temp.toArray(cacheKeyList);*/

        // keySegsList存放所有的key值片段
        HashSet<String> keySegsList = new HashSet<String>();
        // 该字典中存放的是首字母排序的子集和
        ConcurrentHashMap<String, ArrayList<String>> rankDict = new ConcurrentHashMap<String, ArrayList<String>>();

        for (String pyKey : KeySet) {
            if (rankDict.get(pyKey) != null) {
                break;
            }
            //如果pyKey为XiaoMei：则getPyFcSegs返回的值为, ,   即各种key的顺序组合
            HashSet<String> tempkeySegs = getPyFcSegs(pyKey);
            keySegsList.addAll(tempkeySegs);

            /*String[] keySegs = new String[tempkeySegs.size()];
            tempkeySegs.toArray(keySegs);*/

//            keySegsList.addAll(tempkeySegs);
            //{=[], =[], =[], =[]}
            Iterator<String> iterator = tempkeySegs.iterator();
            while (iterator.hasNext()) {
                String ks = iterator.next();
                ArrayList<String> rankDictValue = rankDict.get(ks);
                if (rankDictValue == null) {
                    ArrayList<String> value = new ArrayList<String>(); 
                    value.add(pyKey);
                    rankDict.put(ks, value);
                } else {
                    if (!rankDictValue.contains(pyKey)) {
                        rankDictValue.add(pyKey);
                    }
                }
            }
        }
        
        KeySet.clear();
        KeySet = null;
        
        
        ConcurrentHashMap<Long, ContactInfoNode> myContactInfoDict = myGroupContactInfoDict.get(groupId);
        if( myContactInfoDict == null )
        {
        	myContactInfoDict = new ConcurrentHashMap<Long, ContactInfoNode>();
        	myGroupContactInfoDict.put(groupId, myContactInfoDict);
        }
        
        
        ContactInfoNode myContactInfo = myContactInfoDict.get(contactId);

        if (myContactInfo == null) {
            myContactInfo = new ContactInfoNode();
            myContactInfoDict.put(contactId, myContactInfo);
        }
        

        
        myContactInfo.nameLength = contactName.length();

        Iterator<String> it = cachePyList.iterator();
        StringBuilder sb = new StringBuilder();
        while (it.hasNext()) {
            String element = it.next();
            sb.append(element);
            sb.append("\u0001");
        }
        //XiaoMei42634
        // remove last ,
        if(sb.length()!=0){
            sb.deleteCharAt(sb.length() - 1);
        }
        
        myContactInfo.pinyinData = sb.toString();
        myContactInfo.myRank = rankDict;
//        myContactInfo.phoneNumber = phoneNumber

        myContactInfo.havePhoneNumber = havePhoneNumber;
        
        // myContactInfo.length = [contactName length];
        /*
         * myContactInfo.contactName = [NSString stringWithString:contactName];
         * myContactInfo.pinyinData = [cachePyList
         * componentsJoinedByString:@","]; myContactInfo.myRank = [NSDictionary
         * dictionaryWithDictionary:rankDict];
         */// 为所有key分段建立BitSet和contactinfo dictionary
        
        HashMap<String, BitSet> myDialerDict = myGroupDialerDict.get(groupId);
        if( myDialerDict == null )
        {
        	myDialerDict = new HashMap<String, BitSet>();
        	myGroupDialerDict.put(groupId, myDialerDict);
        }
        
        Iterator<String> keySegsIt = keySegsList.iterator();
        while (keySegsIt.hasNext()) {
            String ks = keySegsIt.next();
            BitSet item = myDialerDict.get(ks);
            if (item == null) {
                item = new BitSet();
            }
            if (!item.get((int) contactId)) {
                item.set((int) contactId);
                myDialerDict.put(ks, item);
            }
        }
    
    
    
    
    
    
    }
    
    
    
    
    public void addPinyinDict(String contactName, long contactIndex, String fuzzyString, 
                              int contactedNumber, boolean havePhoneNumber) {

        if (StringUtil.isEmpty(contactName)) {
            return;
        }
        
        contactName = contactName.replaceAll(StringUtil.SAPCE_REGEX, "");
        ArrayList<String> cachePyList = new ArrayList<String>();
        ArrayList<String> nlPy = new ArrayList<String>();
        
        int iLength = contactName.length();
        if (iLength > 20)
            iLength = 20; // 限定最长分析20字符

        /*
         * cachePyList中存放的是拼音: 如小梅，存放在cachePyList中的为：XiaoMei
         */
        ArrayList<String> retArray = new ArrayList<String>();
        for (int i = 0; i < iLength; i++) {
            // int cacheListCount = [cachePyList count];
            int cacheListCount = cachePyList.size();
            getPinyinReal(contactName.charAt(i), retArray);
            for (String py : retArray) {
                if (cacheListCount > 0) {
                    for (int cacheIdx = 0; cacheIdx < cacheListCount; cacheIdx++) {
                        String temp = cachePyList.get(cacheIdx) + py;
                        nlPy.add(temp);
                    }
                } else {
                    nlPy.add(py);
                }
            }
            cachePyList.clear();
            cachePyList.addAll(nlPy);
            nlPy.clear();
        }
        retArray.clear();
        retArray.add("\u0002");//作为拼音和T9之间的分隔符
        for (String cachePy : cachePyList) {
            retArray.add(getT9StrFromLetters(cachePy));
        }
        //如小梅：cacheT9List中存放的是：[, 42634]： 为分隔符，42634为XiaoMei对应的T9，为9，为6
        cachePyList.addAll(retArray);

        // T9List中存放的是首字母对应的数字，首字母为大写 cacheKeyList存放了所有的首字母，因为一个汉字对应多个拼音:
        // 比如长：Zhang Chang, 如果姓名是长鹏飞,则对应的首字母为ZPF，CPF
        //getKeyFromPinyinList是从cacheT9List中取出key值，如XiaoMei的key值为, , 为分隔符
        HashSet<String> KeySet = getKeyFromPinyinList(retArray);
        /*String[] cacheKeyList = new String[temp.size()];
        temp.toArray(cacheKeyList);*/

        // keySegsList存放所有的key值片段
        HashSet<String> keySegsList = new HashSet<String>();
        // 该字典中存放的是首字母排序的子集和
        ConcurrentHashMap<String, ArrayList<String>> rankDict = new ConcurrentHashMap<String, ArrayList<String>>();

        for (String pyKey : KeySet) {
            if (rankDict.get(pyKey) != null) {
                break;
            }
            //如果pyKey为XiaoMei：则getPyFcSegs返回的值为, ,   即各种key的顺序组合
            HashSet<String> tempkeySegs = getPyFcSegs(pyKey);
            keySegsList.addAll(tempkeySegs);

            /*String[] keySegs = new String[tempkeySegs.size()];
            tempkeySegs.toArray(keySegs);*/

//            keySegsList.addAll(tempkeySegs);
            //{=[], =[], =[], =[]}
            Iterator<String> iterator = tempkeySegs.iterator();
            while (iterator.hasNext()) {
                String ks = iterator.next();
                ArrayList<String> rankDictValue = rankDict.get(ks);
                if (rankDictValue == null) {
                    ArrayList<String> value = new ArrayList<String>(); 
                    value.add(pyKey);
                    rankDict.put(ks, value);
                } else {
                    if (!rankDictValue.contains(pyKey)) {
                        rankDictValue.add(pyKey);
                    }
                }
            }
        }
        
        KeySet.clear();
        KeySet = null;
        
        ContactInfoNode myContactInfo = myContactInfoDict.get(contactIndex);
        
        if (myContactInfo == null) {
            myContactInfo = new ContactInfoNode();
            myContactInfoDict.put(contactIndex, myContactInfo);
        }
        
        if (contactedNumber != -1) {
            myContactInfo.contactedNumber = contactedNumber;
        }
        
        myContactInfo.nameLength = contactName.length();

        Iterator<String> it = cachePyList.iterator();
        StringBuilder sb = new StringBuilder();
        while (it.hasNext()) {
            String element = it.next();
            sb.append(element);
            sb.append("\u0001");
        }
        //XiaoMei42634
        // remove last ,
        if(sb.length()!=0){
            sb.deleteCharAt(sb.length() - 1);
        }
        
        myContactInfo.pinyinData = sb.toString();
        myContactInfo.myRank = rankDict;
//        myContactInfo.phoneNumber = phoneNumber
        if (!StringUtil.isEmpty(fuzzyString)) {
            myContactInfo.fuzzyString = fuzzyString;
        }
        myContactInfo.havePhoneNumber = havePhoneNumber;
        
        // myContactInfo.length = [contactName length];
        /*
         * myContactInfo.contactName = [NSString stringWithString:contactName];
         * myContactInfo.pinyinData = [cachePyList
         * componentsJoinedByString:@","]; myContactInfo.myRank = [NSDictionary
         * dictionaryWithDictionary:rankDict];
         */// 为所有key分段建立BitSet和contactinfo dictionary
        Iterator<String> keySegsIt = keySegsList.iterator();
        while (keySegsIt.hasNext()) {
            String ks = keySegsIt.next();
            BitSet item = myDialerDict.get(ks);
            if (item == null) {
                item = new BitSet();
            }
            if (!item.get((int) contactIndex)) {
                item.set((int) contactIndex);
                myDialerDict.put(ks, item);
            }
        }
    }

    public void addFuzzyString(long contactIndex, String fuzzyString) {
        
        ContactInfoNode node = myContactInfoDict.get(contactIndex);
        if (node != null) {
//            node.phoneNumber = phoneNumber;
            node.fuzzyString = fuzzyString;
        }
    }
    
    public class SearchResult {
        public int rankLevel;//起始字符
        public int matchnameLength;//匹配长度
        public long contactId;
        public boolean telephony;
        public String pinyin;
        public int allNameLength;
    }
    
    public static class HighLightFormat {
        public int rankLevel;//起始字符
        public int matchnameLength;//匹配长度
    }

    HashMap<Integer, SearchResult> searchMap = new HashMap<Integer, SearchResult>();
    StringBuilder key = new StringBuilder();
    TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>> orderSet = null;
    BitSet checkList = new BitSet();
    
    public TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String, 
                   ArrayList<SearchResult>>>>> getContactIndexListByT9(String pinyin, int ifShowPeopleNoPhone, 
                           TreeMap<Integer, ArrayList<Long>> contactedIdMap) {
        if (StringUtil.isEmpty(pinyin)) {
            return null;
        }
        
        searchMap.clear();
        key.setLength(0);
        if (orderSet != null) {
            orderSet.clear();
        }
        checkList.clear();
        
        ArrayList<ArrayList<String>> pinyinList = getPinyinListByReg(pinyin);
        if (pinyinList == null) return null;
        Collections.reverse(pinyinList);
        boolean isSinglePinyin = ((pinyin.length() == 1) && (pinyinList.get(0).size() == 1));
        for (ArrayList<String> pyi : pinyinList) {
//            ArrayList<String> pyi = pinyinList.get(i);
            key.setLength(0);
            sExp.setLength(0);
            //
            // if (bNewInput) break;
            if (mHaveNewInput) {
                break;
            }
            
            if (isSinglePinyin) {
                key.append(pyi.get(0));
                sExp.append(pyi.get(0));
            } else {
                for (String s : pyi) {
                    //
                    // if (bNewInput) break;
                    key.append(s.charAt(0));
                    sExp.append(s);
                    // \uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19
//                    sExp.append("[^,\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019]*?");
                    sExp.append("[^\u0001\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019]*?");
                }
            }
            //
            // if (bNewInput) break
            BitSet cnList = myDialerDict.get(key.toString());
            if (cnList == null) {
                key.setLength(0);
                sExp.setLength(0);
                continue;
            }

            Pattern pattern = Pattern.compile(sExp.toString());
            int nextPosition = cnList.nextSetBit(0);
            while (nextPosition != -1) {
                
                if (mHaveNewInput) {
                    break;
                }
                // while (iter.hasNext()) {
                // Boolean b = (Boolean) iter.next();

                // String tf = (b.booleanValue() ? "T" : "F");
                // if (b.booleanValue()) {
                int currentIndex = nextPosition;
                boolean hasAdded = false;
                
                if (checkList.get(currentIndex)) {
                    nextPosition = cnList.nextSetBit(nextPosition + 1);
                    continue;
                }
                
                ContactInfoNode contactInfo = myContactInfoDict.get((long)currentIndex);
                if (contactInfo == null) {
                    nextPosition = cnList.nextSetBit(nextPosition + 1);
                    continue;
                }
                
                if (ifShowPeopleNoPhone != Constants.SHOW_PEOPLE_WITH_NOPHONENUMBER) {
                    if (!contactInfo.havePhoneNumber) {
                        nextPosition = cnList.nextSetBit(nextPosition + 1);
                        continue;
                    }
                }
                // if (isSinglePinyin) {
                int location = contactInfo.pinyinData.indexOf('\u0002');
                String truePinyin = contactInfo.pinyinData.substring(location+1);
                Matcher match = pattern.matcher(truePinyin);

                SearchResult result = null;
                if (match.find()) {
                    String str = match.group(0);
                    int start = truePinyin.indexOf(str);

                    ArrayList<String> pyKeyList = contactInfo.myRank.get(key.toString());

                    int rankLevel = -1;
                    
                    /*for (String pyKey : pyKeyList) {
                        if (pyKey.equals(key.toString())) {
                            rankLevel = 0;
                            break;
                        }
                    }*/
                    if (pyKeyList.contains(key)) {
                        rankLevel = 0;
                    }

                    if (rankLevel != 0) {
                        int repeatCount = 0;
                        for (int k = start - 1; k >= 0; k--) {
                            char curChar = truePinyin.charAt(k);
//                            if (curChar == ',')
//                                break;
                            if (curChar == 1)
                                break;

//                            if ((curChar >= 18) && (curChar <= 25)) {// KeyTransform:
                                                                     // '2'-'9'
                            if ((curChar < 50) || (curChar > 57)) {// KeyTransform:
                                repeatCount++;
                            }
                        }
                        rankLevel = repeatCount;
                    }
                    boolean ifMatchAll = false;
                    if (key.length() == contactInfo.nameLength) {
                        ifMatchAll = true;
                    }
                    //根据联系次数决定存放的队列
                    if (contactedIdMap != null) {
                        if (contactInfo.contactedNumber > 0) {
                            ArrayList<Long> idItemList = contactedIdMap.get(contactInfo.contactedNumber);
                            if (idItemList == null) {
                                idItemList = new ArrayList<Long>();
                                contactedIdMap.put(contactInfo.contactedNumber, idItemList);
                            }
                            idItemList.add((long) currentIndex);
                            nextPosition = cnList.nextSetBit(nextPosition + 1);
                            //
                            HighLightFormat format = new HighLightFormat();
                            format.rankLevel = rankLevel;
                            format.matchnameLength = key.length();
                            mContactIdPosition.put((long) currentIndex, format);
                            
                            continue;
                        }
                    }
                    result = new SearchResult();
                    result.contactId = currentIndex;
                    //要使用姓名长度，姓名长度短的优先
                    result.matchnameLength = key.length();
                    if (ifMatchAll) {
                        result.matchnameLength += 10;
                    }
                    result.rankLevel = rankLevel;
                    result.telephony = false;
                    
//                    int index = contactInfo.pinyinData.indexOf("\u0001");
                    String pinyinData = contactInfo.pinyinData;
                    int index = 0;
                    int m=0;
                    for (; m<pinyinData.length(); m++) {
                        char curChar = pinyinData.charAt(m);
                        if (curChar == 1)
                            break;
                        if ((curChar >= 65) && (curChar <= 90)) {// Key: 'A'- 'Z'
                            index++;
                        }
                        if (index == 2) break;
                    }
                    
                    result.pinyin = contactInfo.pinyinData.substring(0, m);
                    result.allNameLength = contactInfo.nameLength;
                    
                    if (checkList.get(currentIndex)) {
                        SearchResult searchItem = searchMap.get(currentIndex);
                        if (searchItem.matchnameLength < result.matchnameLength) {
                            searchItem.matchnameLength = result.matchnameLength;
                            searchItem.rankLevel = result.rankLevel;
                            searchItem.allNameLength = result.allNameLength;
                        }
                        nextPosition = cnList.nextSetBit(nextPosition + 1);
                        continue;
                    }
                    hasAdded = true;

                }

                if (hasAdded) {
                    checkList.set(currentIndex);
                    searchMap.put(currentIndex, result);
                }
               
                nextPosition = cnList.nextSetBit(nextPosition + 1);
            }
        }

        //add here
        Iterator<Integer> it = searchMap.keySet().iterator();
        while (it.hasNext()) {
            if (mHaveNewInput) {
                break;
            }
            int contactIdKey = it.next();

            SearchResult result = searchMap.get(contactIdKey);
            if (orderSet == null) {
                orderSet = new TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>>();
            }
            TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>> rankResult = orderSet.get(result.rankLevel);
            //3dimensions: 1:rank level 2:match length 3:name length
            if (rankResult != null) {
                // rankResult.put(result.nameLength, result);
                TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>> resultList = rankResult.get(result.matchnameLength);
                if (resultList != null) {
//                    ArrayList<SearchResult> allnameList = resultList.get(result.pinyin);
                    TreeMap<String, ArrayList<SearchResult>> allnameList = resultList.get(result.allNameLength);
                    if (allnameList == null) {
                        ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
                        resultArray.add(result);

                        allnameList = new TreeMap<String, ArrayList<SearchResult>>();
                        allnameList.put(result.pinyin, resultArray);

                        resultList.put(result.allNameLength, allnameList);
                    } else {
                        ArrayList<SearchResult> resultArray = allnameList.get(result.pinyin);
                        if (resultArray == null) {
                            resultArray = new ArrayList<SearchResult>();
                            resultArray.add(result);

                            allnameList.put(result.pinyin, resultArray);
                        } else {
                            resultArray.add(result);
                        }
                    }
                } else {
                    resultList = new TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>();

                    ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
                    resultArray.add(result);

                    TreeMap<String, ArrayList<SearchResult>> allnamelist = new TreeMap<String, ArrayList<SearchResult>>();
                    allnamelist.put(result.pinyin, resultArray);

                    resultList.put(result.allNameLength, allnamelist);
                    rankResult.put(result.matchnameLength, resultList);
                }
            } else {
                rankResult = new TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>();

                TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>> resultList = new TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>();

                ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
                resultArray.add(result);

                TreeMap<String, ArrayList<SearchResult>> allnamelist = new TreeMap<String, ArrayList<SearchResult>>();
                allnamelist.put(result.pinyin, resultArray);

                resultList.put(result.allNameLength, allnamelist);
                rankResult.put(result.matchnameLength, resultList);
                orderSet.put(result.rankLevel, rankResult);
            }
        }
//        pinyinList.clear();
        searchMap.clear();
        return orderSet;
    }

//    TreeMap<Integer, ArrayList<SearchResult>> orderSetByZm = new TreeMap<Integer, ArrayList<SearchResult>>();
    
	public TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>> getContactIndexListByZm(
			String groupId, String pinyin, int ifShowPeopleNoPhone,
			TreeMap<Integer, ArrayList<Long>> contactedIdMap) {
		if (StringUtil.isEmpty(pinyin)) {
			return null;
		}
		// TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String,
		// ArrayList<SearchResult>>>>> orderSetByZm = null;
		checkList.clear();
		key.setLength(0);
		sExp.setLength(0);
		if (orderSet != null) {
			orderSet.clear();
		}
		String t9Str = getT9StrFromLetters(pinyin);
		ArrayList<ArrayList<String>> pinyinList = getPinyinListByReg(t9Str);
		if (pinyinList == null)
			return null;

		// String special = "()[]\\?+*";
		String special = "()[]{}\\?+.*^|%";
		/*
		 * BitSet checkList = new BitSet(); StringBuffer key = new
		 * StringBuffer(); StringBuffer sExp = new StringBuffer();
		 */

		Collections.reverse(pinyinList);

		for (ArrayList<String> pyi : pinyinList) {
			int startLocation = 0;
			key.setLength(0);
			sExp.setLength(0);

			if (mHaveNewInput) {
				return null;
			}

			for (String s : pyi) {
				if (mHaveNewInput) {
					return null;
				}

				int pyLength = s.length();
				String p = pinyin.substring(startLocation, startLocation
						+ pyLength);
				if (!StringUtil.isEmpty(p)) {
					p = p.substring(0, 1).toUpperCase() + p.substring(1);
				}
				key.append(s.charAt(0));

				int cr = special.indexOf(p);
				if (cr == -1) {
					sExp.append(p);
				} else {
					sExp.append("\\").append(p);
				}
				// sExp.append("[^,A-Z]*?");
				/*
				 * 大写英文字母:\u0041-\u005a 小写英文字母:\u0061-\u007a
				 */
				sExp.append("[^\u0001\u0041-\u005A]*?");
				startLocation += pyLength;
			}
			
			HashMap<String, BitSet> myDialerDict = myGroupDialerDict.get(groupId);
			

			BitSet cnList = myDialerDict.get(key.toString());
			if (cnList == null) {
				key.setLength(0);
				sExp.setLength(0);
				continue;
			}

			Pattern pattern = Pattern.compile(sExp.toString());
			// BitSetIterator iter = new BitSetIterator(cnList);
			int nextPosition = cnList.nextSetBit(0);
			while (nextPosition != -1) {

				if (mHaveNewInput) {
					return null;
				}

				int currentIndex = nextPosition;
				if (checkList.get(currentIndex)) {
					nextPosition = cnList.nextSetBit(nextPosition + 1);
					continue;
				}

				
				
				ConcurrentHashMap<Long, ContactInfoNode> myContactInfoDict = myGroupContactInfoDict.get(groupId);
				
				ContactInfoNode contactInfo = myContactInfoDict
						.get((long) currentIndex);
				// String contactPinyinData = contactInfo.pinyinData;
				// String contactName = contactInfo.contactName;
				if ((contactInfo != null)
						&& !StringUtil.isEmpty(contactInfo.pinyinData)) {

					/*
					if (ifShowPeopleNoPhone != Constants.SHOW_PEOPLE_WITH_NOPHONENUMBER) {
						if (!contactInfo.havePhoneNumber) {
							nextPosition = cnList.nextSetBit(nextPosition + 1);
							continue;
						}
					}
					*/
					Matcher match = pattern.matcher(contactInfo.pinyinData);

					if (match.find()) {

						String str = match.group(0);
						int start = contactInfo.pinyinData.indexOf(str);

						ArrayList<String> pyKeyList = contactInfo.myRank
								.get(key.toString());

						int rankLevel = -1;
						// for (String pyKey : pyKeyList) {
						// if (pyKey.equals(key.toString())) {
						// rankLevel = 0;
						// break;
						// }
						// }
						if (pyKeyList.contains(key.toString())) {
							rankLevel = 0;
							// break;
						}

						if (rankLevel != 0) {
							int repeatCount = 0;
							for (int k = start - 1; k >= 0; k--) {
								char curChar = contactInfo.pinyinData.charAt(k);
								if (curChar == 1)
									break;

								if ((curChar < 97) || (curChar > 122)) {// Key:
																		// 'a'
																		// -
																		// 'z'
									repeatCount++;
								}
							}
							rankLevel = repeatCount;
						}
						boolean ifMatchAll = false;
						if (key.length() == contactInfo.nameLength) {
							ifMatchAll = true;
						}
						// 根据联系次数决定存放的队列
						if (contactedIdMap != null) {
							if (contactInfo.contactedNumber > 0) {
								ArrayList<Long> idItemList = contactedIdMap
										.get(contactInfo.contactedNumber);
								if (idItemList == null) {
									idItemList = new ArrayList<Long>();
									contactedIdMap.put(
											contactInfo.contactedNumber,
											idItemList);
								}
								idItemList.add((long) currentIndex);
								nextPosition = cnList
										.nextSetBit(nextPosition + 1);
								//
								HighLightFormat format = new HighLightFormat();
								format.rankLevel = rankLevel;
								format.matchnameLength = key.length();
								mContactIdPosition.put((long) currentIndex,
										format);

								continue;
							}

						}
						// 要使用姓名长度，姓名长度短的优先
						SearchResult result = new SearchResult();
						result.contactId = currentIndex;
						checkList.set(currentIndex);
						result.matchnameLength = key.length();
						if (ifMatchAll) {
							result.matchnameLength += 10;
						}
						result.rankLevel = rankLevel;
						result.telephony = false;
						result.allNameLength = contactInfo.nameLength;

						String pinyinData = contactInfo.pinyinData;
						int index = 0;
						int m = 0;
						for (; m < pinyinData.length(); m++) {
							char curChar = pinyinData.charAt(m);
							if (curChar == 1)
								break;
							if ((curChar >= 65) && (curChar <= 90)) {// Key:
																		// 'A'-
																		// 'Z'
								index++;
							}
							if (index == 2)
								break;
						}
						result.pinyin = contactInfo.pinyinData.substring(0, m);
						if (orderSet == null) {
							orderSet = new TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>>();
						}
						TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>> rankResult = orderSet
								.get(rankLevel);
						if (rankResult != null) {
							// rankResult.put(result.nameLength, result);
							TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>> resultList = rankResult
									.get(result.matchnameLength);
							if (resultList != null) {
								// ArrayList<SearchResult> allnameList =
								// resultList.get(result.pinyin);
								TreeMap<String, ArrayList<SearchResult>> allnameList = resultList
										.get(result.allNameLength);
								if (allnameList == null) {
									allnameList = new TreeMap<String, ArrayList<SearchResult>>();
									ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
									resultArray.add(result);
									allnameList.put(result.pinyin, resultArray);
									resultList.put(result.allNameLength,
											allnameList);
								} else {
									ArrayList<SearchResult> resultArray = allnameList
											.get(result.pinyin);
									if (resultArray == null) {
										resultArray = new ArrayList<SearchResult>();
										resultArray.add(result);

										allnameList.put(result.pinyin,
												resultArray);
									} else {
										resultArray.add(result);
									}
								}
							} else {
								resultList = new TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>();

								ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
								resultArray.add(result);

								TreeMap<String, ArrayList<SearchResult>> allnamelist = new TreeMap<String, ArrayList<SearchResult>>();
								allnamelist.put(result.pinyin, resultArray);

								resultList.put(result.allNameLength,
										allnamelist);
								rankResult.put(result.matchnameLength,
										resultList);
							}
						} else {
							rankResult = new TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>();

							TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>> resultList = new TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>();

							ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
							resultArray.add(result);

							TreeMap<String, ArrayList<SearchResult>> allnamelist = new TreeMap<String, ArrayList<SearchResult>>();
							allnamelist.put(result.pinyin, resultArray);

							resultList.put(result.allNameLength, allnamelist);
							rankResult.put(result.matchnameLength, resultList);
							orderSet.put(result.rankLevel, rankResult);
						}
					}
				}

				nextPosition = cnList.nextSetBit(nextPosition + 1);
			}
		}

		return orderSet;
	}
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    public TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String,
                   ArrayList<SearchResult>>>>> getContactIndexListByZm(String pinyin, int ifShowPeopleNoPhone,
                           TreeMap<Integer, ArrayList<Long>> contactedIdMap) {
        if (StringUtil.isEmpty(pinyin)) {
            return null;
        }
//        TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>> orderSetByZm  = null;
        checkList.clear();
        key.setLength(0);
        sExp.setLength(0);
        if (orderSet != null) {
            orderSet.clear();
        }
        String t9Str = getT9StrFromLetters(pinyin);
        ArrayList<ArrayList<String>> pinyinList = getPinyinListByReg(t9Str);
        if (pinyinList == null)
            return null;

        // String special = "()[]\\?+*";
        String special = "()[]{}\\?+.*^|%";
        /*BitSet checkList = new BitSet();
        StringBuffer key = new StringBuffer();
        StringBuffer sExp = new StringBuffer();*/

        Collections.reverse(pinyinList);

        for (ArrayList<String> pyi : pinyinList) {
            int startLocation = 0;
            key.setLength(0);
            sExp.setLength(0);

            if (mHaveNewInput) {
                return null;
            }

            for (String s : pyi) {
                if (mHaveNewInput) {
                    return null;
                }

                int pyLength = s.length();
                String p = pinyin.substring(startLocation, startLocation + pyLength);
                if (!StringUtil.isEmpty(p)) {
                    p = p.substring(0, 1).toUpperCase() + p.substring(1);
                }
                key.append(s.charAt(0));

                int cr = special.indexOf(p);
                if (cr == -1) {
                    sExp.append(p);
                } else {
                    sExp.append("\\").append(p);
                }
                // sExp.append("[^,A-Z]*?");
                /*
                 * 大写英文字母:\u0041-\u005a 小写英文字母:\u0061-\u007a
                 */
                sExp.append("[^\u0001\u0041-\u005A]*?");
                startLocation += pyLength;
            }

            BitSet cnList = myDialerDict.get(key.toString());
            if (cnList == null) {
                key.setLength(0);
                sExp.setLength(0);
                continue;
            }

            Pattern pattern = Pattern.compile(sExp.toString());
            // BitSetIterator iter = new BitSetIterator(cnList);
            int nextPosition = cnList.nextSetBit(0);
            while (nextPosition != -1) {

                if (mHaveNewInput) {
                    return null;
                }

                int currentIndex = nextPosition;
                if (checkList.get(currentIndex)) {
                    nextPosition = cnList.nextSetBit(nextPosition + 1);
                    continue;
                }

                ContactInfoNode contactInfo = myContactInfoDict.get((long)currentIndex);
                // String contactPinyinData = contactInfo.pinyinData;
                // String contactName = contactInfo.contactName;
                if ((contactInfo != null) && !StringUtil.isEmpty(contactInfo.pinyinData)) {

                    if (ifShowPeopleNoPhone != Constants.SHOW_PEOPLE_WITH_NOPHONENUMBER) {
                        if (!contactInfo.havePhoneNumber) {
                            nextPosition = cnList.nextSetBit(nextPosition + 1);
                            continue;
                        }
                    }
                    Matcher match = pattern.matcher(contactInfo.pinyinData);

                    if (match.find()) {

                        String str = match.group(0);
                        int start = contactInfo.pinyinData.indexOf(str);

                        ArrayList<String> pyKeyList = contactInfo.myRank.get(key.toString());

                        int rankLevel = -1;
//                        for (String pyKey : pyKeyList) {
//                            if (pyKey.equals(key.toString())) {
//                                rankLevel = 0;
//                                break;
//                            }
//                        }
                        if (pyKeyList.contains(key.toString())) {
                            rankLevel = 0;
//                            break;
                        }

                        if (rankLevel != 0) {
                            int repeatCount = 0;
                            for (int k = start - 1; k >= 0; k--) {
                                char curChar = contactInfo.pinyinData.charAt(k);
                                if (curChar == 1)
                                    break;

                                if ((curChar < 97) || (curChar > 122)) {// Key:
                                                                        // 'a'
                                                                        // -
                                                                        // 'z'
                                    repeatCount++;
                                }
                            }
                            rankLevel = repeatCount;
                        }
                        boolean ifMatchAll = false;
                        if (key.length() == contactInfo.nameLength) {
                            ifMatchAll = true;
                        }
                        //根据联系次数决定存放的队列
                        if (contactedIdMap != null) {
                            if (contactInfo.contactedNumber > 0) {
                                ArrayList<Long> idItemList = contactedIdMap.get(contactInfo.contactedNumber);
                                if (idItemList == null) {
                                    idItemList = new ArrayList<Long>();
                                    contactedIdMap.put(contactInfo.contactedNumber, idItemList);
                                }
                                idItemList.add((long) currentIndex);
                                nextPosition = cnList.nextSetBit(nextPosition + 1);
                                //
                                HighLightFormat format = new HighLightFormat();
                                format.rankLevel = rankLevel;
                                format.matchnameLength = key.length();
                                mContactIdPosition.put((long) currentIndex, format);

                                continue;
                            }

                        }
                        // 要使用姓名长度，姓名长度短的优先
                        SearchResult result = new SearchResult();
                        result.contactId = currentIndex;
                        checkList.set(currentIndex);
                        result.matchnameLength = key.length();
                        if (ifMatchAll) {
                            result.matchnameLength += 10;
                        }
                        result.rankLevel = rankLevel;
                        result.telephony = false;
                        result.allNameLength = contactInfo.nameLength;

                        String pinyinData = contactInfo.pinyinData;
                        int index = 0;
                        int m = 0;
                        for (; m < pinyinData.length(); m++) {
                            char curChar = pinyinData.charAt(m);
                            if (curChar == 1)
                                break;
                            if ((curChar >= 65) && (curChar <= 90)) {// Key:
                                                                     // 'A'- 'Z'
                                index++;
                            }
                            if (index == 2)
                                break;
                        }
                        result.pinyin = contactInfo.pinyinData.substring(0, m);
                        if (orderSet == null) {
                            orderSet = new TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>>();
                        }
                        TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>> rankResult = orderSet.get(rankLevel);
                        if (rankResult != null) {
                            // rankResult.put(result.nameLength, result);
                            TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>> resultList = rankResult.get(result.matchnameLength);
                            if (resultList != null) {
//                                ArrayList<SearchResult> allnameList = resultList.get(result.pinyin);
                                TreeMap<String, ArrayList<SearchResult>> allnameList = resultList.get(result.allNameLength);
                                if (allnameList == null) {
                                    allnameList = new TreeMap<String, ArrayList<SearchResult>>();
                                    ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
                                    resultArray.add(result);
                                    allnameList.put(result.pinyin, resultArray);
                                    resultList.put(result.allNameLength, allnameList);
                                } else {
                                    ArrayList<SearchResult> resultArray = allnameList.get(result.pinyin);
                                    if (resultArray == null) {
                                        resultArray = new ArrayList<SearchResult>();
                                        resultArray.add(result);

                                        allnameList.put(result.pinyin, resultArray);
                                    } else {
                                        resultArray.add(result);
                                    }
                                }
                            } else {
                                resultList = new TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>();

                                ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
                                resultArray.add(result);
                                
                                TreeMap<String, ArrayList<SearchResult>> allnamelist = new TreeMap<String, ArrayList<SearchResult>>();
                                allnamelist.put(result.pinyin, resultArray);
                                
                                resultList.put(result.allNameLength, allnamelist);
                                rankResult.put(result.matchnameLength, resultList);
                            }
                        } else {
                            rankResult = new TreeMap<Integer, TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>>();
                            
                            TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>> resultList = new TreeMap<Integer, TreeMap<String, ArrayList<SearchResult>>>();
                            
                            ArrayList<SearchResult> resultArray = new ArrayList<SearchResult>();
                            resultArray.add(result);
                            
                            TreeMap<String, ArrayList<SearchResult>> allnamelist = new TreeMap<String, ArrayList<SearchResult>>();
                            allnamelist.put(result.pinyin, resultArray);
                            
                            resultList.put(result.allNameLength, allnamelist);
                            rankResult.put(result.matchnameLength, resultList);
                            orderSet.put(result.rankLevel, rankResult);
                        }
                    }
                }

                nextPosition = cnList.nextSetBit(nextPosition + 1);
            }
        }

        return orderSet;
    }
    
    //regular variable
    private StringBuilder sExp = new StringBuilder();
    //fuzzyString
    private StringBuffer temp = new StringBuffer();
    private String TAG = "PinyinSearch";
    // 模糊查询老算法，第一个字符是*号
    public LinkedHashSet<Long> serachForFuzzy(String sInputName, boolean bMohu)
    {
        char ic;
        char lastIc = 0;
        int ilength;
        char ic1, ic2, ic3, ic4;
        LinkedHashSet<Long> contactIds = new LinkedHashSet<Long>();

        sInputName = sInputName.toUpperCase();
        ilength = sInputName.length();
        if (ilength == 0)
            return null;

        // 构造正则表达式
        sExp.setLength(0);
        for (int i = 0; i < ilength; i++) {
            if (mHaveNewInput) {
                break;
            }
            ic = sInputName.charAt(i);
            if (ic == '*') {
                if (lastIc != '*') {
                    sExp.append(".+"); // 通配符，模糊匹配
                }
            } else {
                ic1 = 0;// @"";
                ic2 = 0;// @"";
                ic3 = 0;// @"";
                ic4 = 0;// @"";
                if (ic < 58 && ic > 49) { // 如果是数字输入,获取每个数字对应T9的字母
                    switch (ic) {
                        case 50: // 从数字2开始
                            ic1 = 65; // @"A";
                            ic2 = 66; // @"B";
                            ic3 = 67; // @"C";
                            ic4 = 0; // @"";
                            break;
                        case 51: // 3
                            ic1 = 68; // D
                            ic2 = 69; // E
                            ic3 = 70; // F
                            ic4 = 0; // ""
                            break;
                        case 52: // 4
                            ic1 = 71; // G
                            ic2 = 72; // H
                            ic3 = 73; // I
                            ic4 = 0; // ""
                            break;
                        case 53: // 5
                            ic1 = 74; // J
                            ic2 = 75; // K
                            ic3 = 76; // L
                            ic4 = 0; // ""
                            break;
                        case 54: // 6
                            ic1 = 77; // M
                            ic2 = 78; // N
                            ic3 = 79; // O
                            ic4 = 0; // ""
                            break;
                        case 55: // 7
                            ic1 = 80; // P
                            ic2 = 81; // Q
                            ic3 = 82; // R
                            ic4 = 83; // S
                            break;
                        case 56: // 8
                            ic1 = 84; // T
                            ic2 = 85; // U
                            ic3 = 86; // V
                            ic4 = 0; // ""
                            break;
                        case 57: // 9
                            ic1 = 87; // W
                            ic2 = 88; // X
                            ic3 = 89; // Y
                            ic4 = 90; // Z
                            break;
                        default: // 其他情况都是空
                            break;
                    }
                    sExp.append("[");
                    sExp.append(ic);
                    sExp.append(ic1);
                    sExp.append(ic2);
                    sExp.append(ic3);
                    sExp.append(ic4);
                    sExp.append("]");
                } else {
                    sExp.append("[");
                    sExp.append(ic);
                    sExp.append("]");
                }
                
            }
            lastIc = ic;
        }
        
        Set<Long> contactIdSet = myContactInfoDict.keySet();
        Iterator<Long> it = contactIdSet.iterator();
        
        while (it.hasNext()) {
            if (mHaveNewInput) {
                break;
            }
            long contactId = it.next();
            temp.setLength(0);
            ContactInfoNode contact = myContactInfoDict.get(contactId);
            if (contact != null && contact.fuzzyString != null) {
                temp.append(contact.fuzzyString).append(", ").append(contact.fuzzyString);
                String fuzzyString = temp.toString();
                int ioLen = fuzzyString.length();
                // 输入长度超过当前名字长度，不需要判断，不加入清单
                if (ilength > ioLen) {
                    continue;
                } else {
                    String expStr = sExp.toString();
                    Pattern pattern = Pattern.compile(expStr);
                    Matcher match = pattern.matcher(fuzzyString);
                    try {
                    if (match.find()) {
                        contactIds.add(contactId);
                    }
                    } catch (Exception e) {
                        // Not enough memory for the photo, do nothing.
                        e.printStackTrace();
                    }

                }
            }
        }
        return contactIds;

    }
    
    // 进一步遍历搜寻电话号码
    public LinkedHashSet<Long> searchExp(String sInputName, String internationalCode, String countryCode) {
        Set<Long> contactIdSet = myContactInfoDict.keySet();
        Iterator<Long> it = contactIdSet.iterator();
        LinkedHashSet<Long> contactIds = new LinkedHashSet<Long>();
        
        while (it.hasNext()) {
            
            if (mHaveNewInput) {
                break;
            }
            long contactId = it.next();
            boolean found = false;
            
            ContactInfoNode contact = myContactInfoDict.get(contactId);
            if (contact == null) {
                continue;
            }
//            String strT9 = contact.phoneNumber;
            //ATTENTION:  phone number now not stored in memory, and this interface will be discarded
            String strT9 = "";
            if (StringUtil.isEmpty(strT9)) {
                continue;
            }
            strT9 = strT9.replaceAll("\\(", "");
            strT9 = strT9.replaceAll("\\)", "");
            strT9 = strT9.replaceAll("\\-", "");
            strT9 = strT9.replaceAll(" ", "");
            // 寻找当前数字串在号码数组中的位置,整串查询
            if (!strT9.contains(sInputName)) {
                // 第一次如果没找到，则判断如果+开头，则替换为当前国家冠码，再找一次
                char firstCharacter = sInputName.charAt(0); 
                StringBuffer sb = new StringBuffer();
                if (firstCharacter == '+') {
//                    sb.append(",");
                    sb.append(internationalCode);
                    sb.append(sInputName.substring(1));
                } else {
                    sb.append(sInputName);
                }
                
                if (!strT9.contains(sb.toString())) {
                    // 如果是当前国家冠码开头，则替换为+号后，再找一次，这样保证无论以+开头或者冠码开头，都能正确找到国际电话号码
                    if (sInputName.indexOf(internationalCode) == 0) {
                        sb.setLength(0);
//                        sb.append(",+");
                        sb.append("+");
                        sb.append(sInputName.substring(internationalCode.length()));
                    }
                    if (!strT9.contains(sb.toString())) {
                        // 最后判断，如果号码“0086”开头，则去掉这个0086，重新找一遍
                        // NSString *sIsC = [NSString stringWithFormat:@"%@86",
                        // sInternationalCode];
                        String sIsc = internationalCode + "86";
                        if (sInputName.indexOf(sIsc) == 0) {
                            sb.setLength(0);
                            sb.append(sInputName.substring(sIsc.length()));
                        }

                        if (!strT9.contains(sb.toString())) {
                            // 在中国的情况下，还有最后一种情况，0086已经被去掉替换为0，例如010
                            if (countryCode.equals("86") || countryCode.equals("61")) {
                                if (firstCharacter == '0') {
                                    sb.setLength(0);
                                    sb.append(countryCode);
                                    sb.append(sInputName.substring(1));
                                    if (strT9.contains(sb.toString())) {
                                        found = true;
                                    }
                                }
                            }
                        }
                    } else {
                        found = true;
                    }
                    
                } else {
                    found = true;
                }
            } else {
                found = true;
              /*  int index = strT9.indexOf(sInputName);
                SearchResult result = new SearchResult();
                result.contactId = (int) contactId;
                result.rankLevel = index;
                result.nameLength = sInputName.length();
                result.telephony = true;
                mContactIdPosition.put(contactId, result);*/
            }
            
            if (found) {
                contactIds.add(contactId);
            }
            
        }
        
        return contactIds;
    }

}
